<template>
  <div class="editor-wp c-flex-column">
    <com-header></com-header>
    <div class="c-flex-1 c-flex main">
      <div class="left-container">
        <div class="editor-container c-flex-column">
          <div class="tab-list clearfix">
            <div v-for="(item, index) in data.tab.list" :key="index"
              class="item"
              :class="{active: data.tab.idx == index}"
              @click="toggleTab(index)">{{item.label}}</div>
          </div>
          <div class="editor-content c-flex-1 c-flex-column">
            <div class="editor-head clearfix">
              <div class="languages">
                <div class="item active">JS</div>
              </div>
              <div class="run-btn c-flex" @click="oEchart.init()">
                <svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
                <span>运行</span>
              </div>
            </div>
            <div class="c-flex-column c-flex-1" v-loading="data.loading">
              <div v-show="data.tab.idx == 0" id="aceEditor" class="editor-main c-flex-1"></div>
              <div v-show="data.tab.idx == 1" id="aceAllCodeEditor" class="editor-main c-flex-1"></div>
            </div>
          </div>
        </div>

      </div>
      <div class="c-flex-1 right-container">
        <div class="chart-panel" id="echartMainWrapper" v-loading="data.loading">
          <div id="echartMain"></div>
        </div>
        <div class="tool-panel">
          <div class="btn version">{{data.detail ? data.detail.echartsVersion : ''}}</div>
        </div>
        <div class="preview-status">
          <button class="btn" @click="showState()">下载示例</button>
          <button class="btn" @click="showState()">截图</button>
        </div>
      </div>
    </div>
  </div>
  
</template>
<script setup>
  import {reactive, onMounted, onBeforeUnmount, getCurrentInstance} from "vue";
  
  // 引入组件
  import comHeader from "@/components/com-header.vue";

  // 获取全局的this指向
  const instance = getCurrentInstance();
  const _this = instance.appContext.config.globalProperties;

  let data = reactive({
    loading: true, // 加载中

    detail: '',
    aceCode: '',

    // 按钮组
    tab: {
      idx: 0,
      list: [
        {label: '代码编辑'},
        {label: '完整代码', isOne: true, fn () {
          if (this.isOne) {
            this.isOne = false;
            oAceAll.init();
          } else {
            oAceAll.setValue();
          }
        }}
      ]
    }
  })

  // 实例挂载完成
  onMounted(() => {
    getData();
  });

  // 在销毁之前销毁加载的echart
  onBeforeUnmount(() => {
    oShow.delResource();
  })

  // 获取详情
  let getData = async function () {
    let param = {
      cid: _this.$route.query.id
    }
    let res = await _this.$api.chartDetail(param);
    let resData = res.data;
    data.aceCode = resData.code;

    let detail = {};
    for (let key in resData) {
      if (key != 'code') {
        detail[key] = resData[key];
      }
    }
    data.detail = detail;

    // 初始化右侧图表
    await oShow.init(); // 判断是否已经引入成功
    oEchart.init(); // 初始化

    // 初始化左侧ace-editor，oAce改变时会自动更新图表
    oAce.init();
  }

  // 切换按钮组
  const toggleTab = function (idx) {
    let item = data.tab.list[idx];
    data.tab.idx = idx;
    if (item.fn) {
      item.fn();
    }
  }

  // 功能开发中
  const showState = function () {
    ElMessage({
      message: '此功能正在开发中',
      type: 'warning',
    })
  }


  let oAce = {
    editor: null, // ace-editor对象
    init () {
      this.editor = ace.edit('aceEditor');
      this.editor.session.setMode('ace/mode/javascript'); // 设置语言
      this.editor.setTheme('ace/theme/tomorrow'); // 设置主题
      this.editor.setOptions({
        enableBasicAutocompletion: true,
        enableSnippets: true,
        enableLiveAutocompletion: true// 设置自动提示
      })

      this.editor.getSession().on('change', function(e) {
        oEchart.doAce(); // 更新图表
        data.loading = false;
      });
      this.setValue(data.aceCode);
    },
    // 设置ace-editor内容文本
    setValue (code) {
      this.editor.setValue(code, -1);
    },
    getValue () {
      return this.editor.getValue();
    }
  }

  // 显示完整代码
  let oAceAll = {
    editor: null, // ace-editor对象
    init () {
      this.editor = ace.edit('aceAllCodeEditor');
      this.editor.session.setMode('ace/mode/javascript'); // 设置语言
      this.editor.setTheme('ace/theme/tomorrow'); // 设置主题
      this.editor.setOptions({
        enableBasicAutocompletion: true,
        enableSnippets: true,
        enableLiveAutocompletion: true// 设置自动提示
      })
      // 设置编辑器只读
      this.editor.setReadOnly(true);
      this.setValue();
    },
    setValue () {
      // 显示完整代码
      let code = `import * as echarts from 'echarts';\n\nvar chartDom = document.getElementById('main');\nvar myChart = echarts.init(chartDom);\nvar option;\n\n${data.aceCode}\n\noption && myChart.setOption(option);\n\n\n`;
      this.editor.setValue(code, -1);
    }
  }

  let oShow = {
    domClass: 'echartsScript',
    externalClass: 'externalScripts', // 外部资源
    loadNum: 0, // 加载资源的数量

    // 添加资源
    addResource (list) {
      return new Promise(async (resolve, reject) => {
        for (let i = 0; i < list.length; i++) {
          let item = list[i];
          try {
            await this.addScript(item.classname, item.src);
            if (i == list.length -1) {
              resolve();
            }
          } catch (err) {
            console.log("加载资源出错了：" + item.src);
            reject();
            break;
          }
        }
      })
    },
    // 删除资源
    delResource () {
      this.delScript(this.domClass);
      if (data.detail.externalScripts) {
        this.delScript(this.externalClass);
      }
    },
    // 添加echarts
    addScript (classname, src) {
      return new Promise((resolve, reject) => {
        let dom = document.createElement('script');
        dom.className = classname;
        dom.src = src;
        document.body.appendChild(dom);
        dom.onload = () => {
          resolve();
        }
        dom.onerror = () => {
          reject();
        }
      })
    },
    // 删除资源链接
    delScript (classname) {
      let aDom = document.querySelectorAll('.' + classname);
      for (let i = 0; i < aDom.length; i++) {
        document.body.removeChild(aDom[i]);
      }
    },
    // 初始化完成执行
    init () {
      let list = [
        {classname: this.domClass, src: `https://cdn.jsdelivr.net/npm/echarts@${data.detail.echartsVersion}/dist/echarts.min.js`}
      ]
      if (data.detail.externalScripts) {
        list.push({classname: this.externalClass, src: data.detail.externalScripts});
      }
      return this.addResource(list);
    },
  }

  // echart
  let oEchart = {
    wrapperId: 'echartMainWrapper',
    wrapper: null,
    domId: 'echartMain',
    dom: null,
    chart: null,
    // 初始化
    init () {
      this.wrapper = document.getElementById(this.wrapperId);
      this.wrapper.innerHTML = '';
      this.dom = document.createElement("div");
      this.dom.setAttribute("id", this.domId);
      this.dom.style = "width: 100%;height: 100%;";
      this.wrapper.appendChild(this.dom);

      this.chart = window.echarts.init(this.dom);

      window.removeEventListener('resize', resize);
      window.addEventListener('resize', resize);
      function resize () {
        oEchart.chart.resize();
      }
    },
    // 执行ace-cdoe，type为true，则重新渲染图标
    doAce () {
      let option;
      eval(oAce.getValue());
      option && this.chart.setOption(option);
    },
  }


</script>
<style lang="scss" scoped>
.editor-wp {
  height: 100vh;
  .main {
    background: #F2F3F9;
  }

  .left-container {
    width: 40%;
    height: 100%;
    border-right: 1px solid #DBDEE5;
  }
  .editor-container {
    height: 100%;
    .tab-list {
      .item {
        float: left;
        padding: 0 20px;
        height: 34px;
        line-height: 34px;
        cursor: pointer;
        &.active {
          color: #409EFF;
          background-color: #FFF;
          border-right-color: #DCDFE6;
          border-left-color: #DCDFE6;
        }
        &:hover {
          color: #409EFF;
        }
      }
    }
    .editor-content {
      overflow: hidden;
      .editor-head {
        position: relative;
        z-index: 2;
        background: #fff;
        height: 30px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        .languages {
          float: left;
          padding: 2px 10px;
          .item {
            padding: 0 10px;
            color: #3178c6;
            border-radius: 3px;
            cursor: pointer;
            line-height: 26px;
            font-size: 12px;
            font-weight: bold;
            &.active {
              background: #f7df1e;
              color: #000;
            }
          }
        }
        .run-btn {
          float: right;
          padding: 5px  10px;
          background: #409eff;
          color: #fff;
          line-height: 20px;
          height: 100%;
          cursor: pointer;
          svg {
            width: 15px;
            height: 15px;
          }
        }
      }
      .editor-main {
        background: #fff;
      }
    }
  }

  .right-container {
    position: relative;
    height: 100%;
    .chart-panel {
      position: absolute;
      top: 42px;
      right: 15px;
      bottom: 50px;
      left: 15px;
      box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 20px;
      border-radius: 5px;
      background: #fff;
      overflow: hidden;
      padding: 10px;
    }
    .tool-panel {
      position: absolute;
      top: 0;
      right: 0;
      left: 0;
      padding-top: 5px;
      padding-left: 15px;
      padding-right: 15px;
      text-align: right;
      .btn {
        display: inline-block;
      }
      .btn + .btn {
        margin-left: 10px;
      }
      .version {
        padding: 0 15px;
        height: 28px;
        border: 1px solid #D3D5DC;
        line-height: 26px;
        text-align: center;
        min-width: 80px;
        background: #fff;

      }
    }
    .preview-status {
      position: absolute;
      bottom: 5px;
      left: 0;
      right: 0;
      height: 30px;
      padding: 0 20px;
      overflow: hidden;
      .btn {
        margin-right: 10px;
        padding: 0 15px;
        height: 28px;
        border: 1px solid #DCDFE6;
        background: #fff;
        border-radius: 3px;
        font-size: 12px;
        color: #606266;
        cursor: pointer;
        transition: .1s;
        &:hover {
          color: #409EFF;
          border-color: #c6e2ff;
          background-color: #ecf5ff;
        }
      }
    }
  }
}
</style>